2021.9.3更新: 調整了一些block scope的敘述。
scope 可以翻譯成作用域,意即 variable能被調用的範圍。
→ 也就是說,如果一個variable不在當下執行的scope裡,對當前的scope來說根本看不到variable這個東西,所以沒辦法調用。
(補充: 在JS裡,所有的object和function也都是variable。)
而 scope 又分為
只要一個variable宣告在所有的function之外,我們將variable稱為 global variable(全域變數)。
被宣告為global variable就會擁有Global Scope。
這會造成整個script都是它的作用域! 而該頁面的所有的funciton和script都可以調用它。
舉例來說:
// a has Global Scope; All scripts can access it.
let a = "apples"
console.log( "Winnie would eat " + a);
// output: Winnie would eat apples.
// a has Global Scope; All functions can access it.
let a = "apples"
function eat(){
console.log( "Mary would eat " + a);
}
eat(); // output: Mary would eat apples.
以上面的舉例而言,因為a
被宣告在eat()
這個function外,所以不管在function裡或整個script都可以有效的印出a。
在JS裡,每一個function都會有一個Function Scope。
而 被定義在function內部的variable,便不能在function外被調用。
再看個例子:
// a isn't accessible (visible) from outside the function.
function f(){
let a = "apple";
}
console.log( "Mary would eat " + a);
// ReferenceError: a is not defined
a
被宣告在f()
裡,因此想從f()
外調用a
就會出現ReferenceError,意思是對整個global來說a
並不存在。
// a is accessible in the function
function f(){
let a = "apple";
console.log( "Mary would eat " + a);
}
f();
// output: Mary would eat apple
a
的scope就是function scope,而整個f()
都是a
可以被調用的範圍(scope)。
那如果是更多分層的函式呢? 可以在延伸到下一個例子:
// a is accessible in the f2()
function f(){
let a = "apple";
function f2(){
console.log( "Winnie wouldn't eat " + a);
}
f2();
}
f();
// output: Winnie wouldn't eat apple
MDN的文件有提到: 如果有階層關係,基本上子階層會可以調用父級階層裡的變數。
講白話是,像f2()
是在f()
裡的函式,但因為整個f()都是a的scope,所以在f2()裡調用a也會成功。
function f(){
let a = "apple";
function f2(){
console.log( "Winnie wouldn't eat " + a);
}
}
f2(); // ReferenceError: f2 is not defined
最後是,因為function也是variable的一種,
這個例子的情況跟在f()
外印出a
是一樣的,都會造成讀不到f2
。
因為ES6新增了 let
和 const
,
這兩個 keyword 能建立 Block Scope。
let
或const
的宣告,只在{大括號}中有效,無法從{}外被調用。
(→ let
, var
, const
都有global scope和function scope,但只有let
和const
有block scope)
{block scope}通常指兩種情況:
if(true){
let a = "apple";
}
console.log(a); // ReferenceError: a is not defined
→ var
並沒有Block Scope,所以就算被寫在{大括號}裡,也可以從{}外被調用。
if(true){
var a = "apple";
}
console.log(a); // output: apple
另一種block scope的情況,還有在for loop裡面:
for(let i=0; i<=10; i++){
console.log(i);
// output: 0, 1, 2, ... 10
}
console.log("out of the loop: " + i);
// ReferenceError: i is not defined
在(小括號)裡宣告let i=0
,只能在{大括號}裡被調用。
出了{大括號}就會出錯。
for(var i=0; i<=10; i++){
console.log(i);
// output: 0, 1, 2, ... 10
}
console.log("out of the loop: " + i);
// out of the function: 11
在(小括號)裡宣告var i=0
,在{大括號}外也可以成功被調用。
要注意這裡的{大括號}跟 function(){}的大括號是不一樣的,var定義在f(),如果從整個global調用,一樣是function scope的概念,所以會出錯。
function f(){
var a = "apple";
}
console.log(a);
// ReferenceError: a is not defined
---總結重點---
scope 可以翻譯成作用域,意即 變數能被調用的範圍 。
scope 又分為:
參考資料
JavaScript Scope - w3schools
Scope - MDN
【如內文有誤還請不吝指教>< 並感謝閱覽至此的各位:D 】
---正文結束---